#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h> // variable argument lists
#include <string.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <syslog.h>
#include <time.h>
#include "ipcd.h"

/** ISSUES
- Decide whether sem_unlink is necessary when argument check fails?
- Remove unnecessary header files!!
*/

void log_message(char *filename, const char* format, ...) {
	FILE *logfile;
	logfile = fopen(filename, "a");
	if (!logfile) return;
	va_list list;
	va_start( list, format );
	vfprintf(logfile, format, list);
	va_end( list );
	fprintf(logfile, "\n");
    	fclose(logfile);
}


int main(int argc, char *argv[]) {
	
    char  *fname = {0};
    int shmid;
    key_t key;
    shmseg_t *shm;
    sem_t *signal_in, *signal_out, *signal_green;

    fname =(char *)malloc((strlen("logtest")+1)*sizeof(char));
    strcpy(fname,"logtest");
    
    /* We need to get the segment named
      "69", created by the server. */
    key = 69;

    if(argv[1]== NULL) {
    	printf("no argument exiting\n");
    	exit(0);
    } else if ( atoi(argv[1]) > MAX_FIB_ARG64 ) {
    	printf("Max argument cannot be greater than %d\n", MAX_FIB_ARG64);
    	exit(0);

    }  else if ( atoi(argv[1]) < 0 ) {
    	printf("argument cannot be negative\n");
    	exit(0);

    }  else {

            /* Locate the segment. */
            if ((shmid = shmget(key, sizeof(shmseg_t), 0666)) < 0) {
        	perror("shmget");
        	exit(1);
            }

            /* Attach the segment to address space of the client */
            if ((shm = shmat(shmid, NULL, 0)) == (shmseg_t *) -1) {
        	perror("shmat");
        	exit(1);
            }


            /* Open semaphores, create if not exist */
            if ( (signal_in = sem_open(SEMAPHORE_INPUT, 0 , 0666,0)) == SEM_FAILED ) {
        	    log_message(fname ,"Error sem_open");
        	    exit(1);
            }

            if ( (signal_out = sem_open(SEMAPHORE_OUTPUT, 0 , 0666,0)) == SEM_FAILED ) {
        	    log_message(fname ,"Error sem_open");
        	    exit(1);
            }

            if ( (signal_green = sem_open(SEMAPHORE_CHILD, O_CREAT , 0666,1)) == SEM_FAILED ){
        	    log_message(fname ,"Error sem_green");
        	    exit(1);
            }


            /************** CRITICAL SECTION ***********************/

            sem_wait(signal_green);	 //semaphore to sync clients
            shm->n = atoi (argv[1]);	 // write var "n" at shared memory

            sem_post(signal_in);	 //notify server

            sem_wait(signal_out);	 //wait result from server

            //print out result
            printf("Process %d -- Fib(%d) = %.0f\n", getpid(), shm->n, shm->fibonacci );
            fflush(stdout);

            sem_post(signal_green);	 //release semaphore to allow other clients

            /**************END OF CRITICAL SECTION *****************/

            /*** Detach shared memory area from client's address space ***/
            if ((shmdt(shm)) == -1) {
               perror("shmdt");
               exit(1);
            }

            /*** close all used semaphores by the client ***/
            if (sem_close(signal_in))	{ log_message(fname ,"Error sem_close"); exit(1);}  
            if (sem_close(signal_out))  { log_message(fname ,"Error sem_close"); exit(1);}
            if (sem_close(signal_green)){ log_message(fname ,"Error sem_close"); exit(1);}

            exit(0); 

    }

}
